'use client';

import { type ChangeEvent, useRef, useState } from 'react';
import { useMutation } from '@tanstack/react-query';
import { uploadAvatarFile } from '@/services/api';
import Script from 'next/script';
import useToast, { LoginReminderContent } from '@/hooks/useToast';
import type { IAvatarPageContext } from '@/contexts/avatar';
import { AvatarPageContext } from '@/contexts/avatar';

export default function AvatarPage({
  source,
  translatedFields,
}: IAvatarPageContext) {
  const path = source.path;
  const cropperImageRef = useRef(null);
  const cropperSelectionRef = useRef(null);
  const [isEdit, setIsEdit] = useState(!!path.user?.details.largeAvatarUrl);
  const [form, setForm] = useState({
    avatar: '',
    file: '',
    fileObjectUrl: '',
  });
  const { show } = useToast();

  const uploadAvatarFileMutation = useMutation(uploadAvatarFile);

  function clearUploadData() {
    if (form.fileObjectUrl) {
      URL.revokeObjectURL(form.fileObjectUrl);
    }
    setForm({
      avatar: '',
      file: '',
      fileObjectUrl: '',
    });
  }

  async function handleCallback(file: Blob) {
    if (!file) {
      show({
        type: 'DANGER',
        message: translatedFields.fileNotFound,
      });
      return;
    }

    try {
      await uploadAvatarFileMutation.mutateAsync({
        data: {
          file,
        },
      });

      setIsEdit(true);
      clearUploadData();

      show({
        type: 'SUCCESS',
        message: isEdit
          ? translatedFields.updateAvatarComplete
          : translatedFields.uploadAvatarComplete,
      });

      setTimeout(() => {
        show({
          type: 'INFO',
          message: translatedFields.returnToHomePage,
        });
      }, 1000);

      setTimeout(() => {
        location.href = `/users/${path.user!.id}`;
      }, 1500);
    } catch (e) {
      uploadAvatarFileMutation.reset();
      show({
        type: 'DANGER',
        message: e,
      });
    }
  }

  async function onClickUpload() {
    if (isEdit) {
      if (!confirm(translatedFields.confirmUpdateExistingAvatar)) {
        return;
      }
    }

    if (!path.user) {
      show({
        title: translatedFields.loginPrompt,
        content: <LoginReminderContent />,
      });
      return;
    }

    const current = cropperSelectionRef.current;
    if (!current || !cropperImageRef.current) {
      show({
        type: 'DANGER',
        message: translatedFields.cropElementNotFound,
      });
      return;
    }

    const { file } = form;
    if (!file) {
      show({
        type: 'DANGER',
        message: translatedFields.fileNotUploaded,
      });
      return;
    }

    try {
      // @ts-ignore
      const canvas = await current.$toCanvas({
        // @ts-ignore
        beforeDraw: (context, canvas) => {
          const { width, height } = canvas;

          if (width !== 260 || height !== 260) {
            const message = translatedFields.invalidCropDimensions;
            show({
              type: 'DANGER',
              message,
            });
            return Promise.reject(message);
          }
          return Promise.resolve();
        },
      });

      // @ts-ignore
      canvas.toBlob(handleCallback, file.type, 1);
    } catch (e: any) {
      show({
        type: 'DANGER',
        message: e,
      });
    }
  }

  function onClickTop() {
    if (cropperImageRef.current) {
      // @ts-ignore
      cropperImageRef.current.$translate(0, -6);
    }
  }

  function onClickBottom() {
    if (cropperImageRef.current) {
      // @ts-ignore
      cropperImageRef.current.$translate(0, 6);
    }
  }

  function onClickLeft() {
    if (cropperImageRef.current) {
      // @ts-ignore
      cropperImageRef.current.$translate(-6, 0);
    }
  }

  function onClickRight() {
    if (cropperImageRef.current) {
      // @ts-ignore
      cropperImageRef.current.$translate(6, 0);
    }
  }

  function onClickPlus() {
    if (cropperImageRef.current) {
      // @ts-ignore
      cropperImageRef.current.$zoom(0.1);
    }
  }

  function onClickDash() {
    if (cropperImageRef.current) {
      // @ts-ignore
      cropperImageRef.current.$zoom(-0.1);
    }
  }

  function onClickReset() {
    if (cropperImageRef.current && cropperSelectionRef.current) {
      // @ts-ignore
      cropperImageRef.current.$resetTransform();
      // @ts-ignore
      cropperImageRef.current.$center('cover');
      // @ts-ignore
      cropperSelectionRef.current.$change(0, 0, 260, 260);
      // @ts-ignore
      cropperSelectionRef.current.$center();
    }
  }

  function onChangeForm(
    e: ChangeEvent<HTMLTextAreaElement | HTMLInputElement>,
  ) {
    const name = e.target.name;
    const value = e.target.value;

    if (name === 'avatar') {
      if (form.fileObjectUrl) {
        URL.revokeObjectURL(form.fileObjectUrl);
      }

      const file = (e.target as any).files[0];
      const fileObjectUrl = URL.createObjectURL(file);
      setForm({
        ...form,
        [name]: value,
        file,
        fileObjectUrl,
      });
    }
  }

  function onLoadCropper() {
    if (cropperImageRef.current && cropperSelectionRef.current) {
      // @ts-ignore
      cropperImageRef.current.$ready(() => {
        // @ts-ignore
        cropperSelectionRef.current.$center();
      });
    }
  }

  return (
    <AvatarPageContext.Provider value={{ source, translatedFields }}>
      <div className="col px-2 py-4">
        <div className="card border-0">
          <div className="card-body py-4">
            <div className="lead text-center mt-4">
              {isEdit
                ? translatedFields.editAvatar
                : translatedFields.uploadNewAvatar}
            </div>
            <div className="row my-5 mx-0">
              <div className="col d-flex align-items-center justify-content-center flex-column">
                {/*// @ts-ignore*/}
                <cropper-canvas
                  style={{ width: 330, height: 330 }}
                  id="cropper-canvas"
                  background
                >
                  {/*// @ts-ignore*/}
                  <cropper-image
                    ref={cropperImageRef}
                    rotatable="false"
                    skewable="false"
                    id="cropper-image"
                    src={form.fileObjectUrl || '/images/avatar.png'}
                    alt="avatar"
                  >
                    {/*// @ts-ignore*/}
                  </cropper-image>
                  {/*// @ts-ignore*/}
                  <cropper-shade></cropper-shade>
                  {/*// @ts-ignore*/}
                  <cropper-handle action="select" plain></cropper-handle>
                  {/*// @ts-ignore*/}
                  <cropper-selection
                    ref={cropperSelectionRef}
                    width="260"
                    height="260"
                    id="cropper-selection"
                    movable
                    resizable
                    outlined
                  >
                    {/*// @ts-ignore*/}
                    <cropper-grid role="grid" hidden></cropper-grid>
                    {/*// @ts-ignore*/}
                    <cropper-crosshair centered></cropper-crosshair>
                    {/*// @ts-ignore*/}
                    <cropper-handle
                      className="rounded-circle"
                      action="move"
                      theme-color="rgba(255, 255, 255, 0.35)"
                    >
                      {/*// @ts-ignore*/}
                    </cropper-handle>
                    {/*// @ts-ignore*/}
                    <cropper-handle action="n-resize" hidden></cropper-handle>
                    {/*// @ts-ignore*/}
                    <cropper-handle action="e-resize" hidden></cropper-handle>
                    {/*// @ts-ignore*/}
                    <cropper-handle action="s-resize" hidden></cropper-handle>
                    {/*// @ts-ignore*/}
                    <cropper-handle action="w-resize" hidden></cropper-handle>
                    {/*// @ts-ignore*/}
                    <cropper-handle action="ne-resize" hidden>
                      {/*// @ts-ignore*/}
                    </cropper-handle>
                    {/*// @ts-ignore*/}
                    <cropper-handle action="nw-resize" hidden>
                      {/*// @ts-ignore*/}
                    </cropper-handle>
                    {/*// @ts-ignore*/}
                    <cropper-handle action="se-resize" hidden>
                      {/*// @ts-ignore*/}
                    </cropper-handle>
                    {/*// @ts-ignore*/}
                    <cropper-handle action="sw-resize" hidden>
                      {/*// @ts-ignore*/}
                    </cropper-handle>
                    {/*// @ts-ignore*/}
                  </cropper-selection>
                  {/*// @ts-ignore*/}
                </cropper-canvas>
                <div className="hstack gap-2 flex-wrap justify-content-center my-5">
                  <button onClick={onClickTop} type="button" className="btn">
                    {translatedFields.moveUp}
                  </button>
                  <button onClick={onClickBottom} type="button" className="btn">
                    {translatedFields.moveDown}
                  </button>
                  <button onClick={onClickLeft} type="button" className="btn">
                    {translatedFields.moveLeft}
                  </button>
                  <button onClick={onClickRight} type="button" className="btn">
                    {translatedFields.moveRight}
                  </button>
                  <button onClick={onClickPlus} type="button" className="btn">
                    {translatedFields.zoomIn}
                  </button>
                  <button onClick={onClickDash} type="button" className="btn">
                    {translatedFields.zoomOut}
                  </button>
                  <button onClick={onClickReset} type="button" className="btn">
                    {translatedFields.update}
                  </button>
                </div>
              </div>
              <div className="col d-flex align-items-center justify-content-center flex-column">
                <div className="row">
                  <div className="col">
                    <div className="input-group">
                      <input
                        disabled={uploadAvatarFileMutation.isLoading}
                        type="file"
                        accept="image/*"
                        className="form-control"
                        id="avatar"
                        name="avatar"
                        value={form.avatar}
                        onChange={onChangeForm}
                        aria-describedby="inputGroupFileAddon04"
                        aria-label="Upload"
                      />
                      <button
                        onClick={onClickUpload}
                        disabled={uploadAvatarFileMutation.isLoading}
                        className="btn btn-outline-secondary"
                        type="button"
                        id="inputGroupFileAddon04"
                      >
                        {uploadAvatarFileMutation.isLoading && (
                          <span
                            className="spinner-border spinner-border-sm me-2"
                            role="status"
                            aria-hidden="true"
                          ></span>
                        )}
                        {isEdit
                          ? translatedFields.update
                          : translatedFields.uploadNewAvatar}
                      </button>
                    </div>
                    <ol className="form-text">
                      <li>{translatedFields.selectAvatarToCrop}</li>
                      <li>{translatedFields.zoomWithMouseOrButton}</li>
                    </ol>
                  </div>
                </div>
                <div className="row my-5">
                  <div className="col d-flex justify-content-center align-items-center">
                    {/*// @ts-ignore*/}
                    <cropper-viewer
                      className="rounded-circle"
                      selection="#cropper-selection"
                      style={{ width: 260 }}
                    >
                      {/*// @ts-ignore*/}
                    </cropper-viewer>
                  </div>
                </div>
              </div>
            </div>
          </div>
        </div>
      </div>
      <Script src="/lib/cropper.min.js" onLoad={onLoadCropper} />
    </AvatarPageContext.Provider>
  );
}
